1   /*
2    * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.
8    *
9    * This code is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12   * version 2 for more details (a copy is included in the LICENSE file that
13   * accompanied this code).
14   *
15   * You should have received a copy of the GNU General Public License version
16   * 2 along with this work; if not, write to the Free Software Foundation,
17   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18   *
19   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20   * or visit www.oracle.com if you need additional information or have any
21   * questions.
22   */
23  /*
24   * @test
25   * @bug 4449637
26   * @summary Basic acceptance test for international J2RE. Verifies that the
27   * most important locale data and character converters exist and are
28   * minimally functional.
29   */
30  
31  import java.io.UnsupportedEncodingException;
32  import java.text.DateFormat;
33  import java.util.Calendar;
34  import java.util.Date;
35  import java.util.Locale;
36  import java.util.TimeZone;
37  
38  public class InternationalBAT {
39  
40      public static void main(String[] args) {
41          boolean pass = true;
42          if (!testRequiredLocales()) {
43              pass = false;
44          }
45          if (!testRequiredEncodings()) {
46              pass = false;
47          }
48  
49          if (!pass) {
50              System.out.println("\nSome tests failed.\n"
51                      + "If you installed the US-only J2RE for Windows, "
52                      + "failures are expected and OK.\n"
53                      + "If you installed the international J2RE, or any J2SDK, "
54                      + "or if this occurs on any platform other than Windows, "
55                      + "please file a bug report.\n"
56                      + "Unfortunately, this test cannot determine whether you "
57                      + "installed a US-only J2RE, an international J2RE, or "
58                      + "a J2SDK.\n");
59              throw new RuntimeException();
60          }
61      }
62  
63      // We require the "fully supported locales" for java.util and java.text:
64      // http://webwork.eng/j2se/1.4/docs/guide/intl/locale.doc.html#util-text
65  
66      private static Locale[] requiredLocales = {
67          new Locale("ar", "SA"),
68          new Locale("zh", "CN"),
69          new Locale("zh", "TW"),
70          new Locale("nl", "NL"),
71          new Locale("en", "AU"),
72          new Locale("en", "CA"),
73          new Locale("en", "GB"),
74          new Locale("en", "US"),
75          new Locale("fr", "CA"),
76          new Locale("fr", "FR"),
77          new Locale("de", "DE"),
78          new Locale("iw", "IL"),
79          new Locale("hi", "IN"),
80          new Locale("it", "IT"),
81          new Locale("ja", "JP"),
82          new Locale("ko", "KR"),
83          new Locale("pt", "BR"),
84          new Locale("es", "ES"),
85          new Locale("sv", "SE"),
86          new Locale("th", "TH"),
87      };
88  
89      // Date strings for May 10, 2001, for the required locales
90      private static String[] requiredLocaleDates = {
91          "10 \u0645\u0627\u064A\u0648, 2001",
92          "2001\u5E745\u670810\u65E5 \u661F\u671F\u56DB",
93          "2001\u5E745\u670810\u65E5 \u661F\u671F\u56DB",
94          "donderdag 10 mei 2001",
95          "Thursday, 10 May 2001",
96          "Thursday, May 10, 2001",
97          "Thursday, 10 May 2001",
98          "Thursday, May 10, 2001",
99          "jeudi 10 mai 2001",
100         "jeudi 10 mai 2001",
101         "Donnerstag, 10. Mai 2001",
102         "\u05D9\u05D5\u05DD \u05D7\u05DE\u05D9\u05E9\u05D9 10 \u05DE\u05D0\u05D9 2001",
103         "\u0917\u0941\u0930\u0941\u0935\u093E\u0930, \u0967\u0966 \u092E\u0908, \u0968\u0966\u0966\u0967",
104         "gioved\u00EC 10 maggio 2001",
105         "2001\u5E745\u670810\u65E5", // ja_JP
106         "2001\uB144 5\uC6D4 10\uC77C \uBAA9\uC694\uC77C",
107         "Quinta-feira, 10 de Maio de 2001",
108         "jueves 10 de mayo de 2001",
109         "den 10 maj 2001",
110         "\u0E27\u0E31\u0E19\u0E1E\u0E24\u0E2B\u0E31\u0E2A\u0E1A\u0E14\u0E35\u0E17\u0E35\u0E48 10 \u0E1E\u0E24\u0E29\u0E20\u0E32\u0E04\u0E21 \u0E1E.\u0E28. 2544",
111     };
112 
113     private static boolean testRequiredLocales() {
114         boolean pass = true;
115 
116         TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
117         Calendar calendar = Calendar.getInstance(Locale.US);
118         calendar.clear();
119         calendar.set(2001, 4, 10, 12, 0, 0);
120         Date date = calendar.getTime();
121 
122         Locale[] available = Locale.getAvailableLocales();
123         for (int i = 0; i < requiredLocales.length; i++) {
124             Locale locale = requiredLocales[i];
125             boolean found = false;
126             for (int j = 0; j < available.length; j++) {
127                 if (available[j].equals(locale)) {
128                     found = true;
129                     break;
130                 }
131             }
132             if (!found) {
133                 System.out.println("Locale not available: " + locale);
134                 pass = false;
135             } else {
136                 DateFormat format =
137                         DateFormat.getDateInstance(DateFormat.FULL, locale);
138                 String dateString = format.format(date);
139                 if (!dateString.equals(requiredLocaleDates[i])) {
140                     System.out.println("Incorrect date string for locale "
141                             + locale + ". Expected: " + requiredLocaleDates[i]
142                             + ", got: " + dateString);
143                     pass = false;
144                 }
145             }
146         }
147         return pass;
148     }
149 
150     // We require the encodings of the fully supported writing systems:
151     // http://webwork.eng/j2se/1.4/docs/guide/intl/locale.doc.html#jfc
152 
153     private static String[] requiredEncodings = {
154         "Cp1256",
155         "MS936",
156         "MS950",
157         "Cp1255",
158         "MS932",
159         "MS949",
160         "Cp1252",
161         "MS874",
162         "ISO8859_6",
163         "EUC_CN",
164         "UTF8",
165         "GBK",
166         "EUC_TW",
167         "ISO8859_8",
168         "EUC_JP",
169         "PCK",
170         "EUC_KR",
171         "ISO8859_1",
172         "ISO8859_15",
173         "TIS620",
174     };
175 
176     // one sample locale each for the required encodings
177 
178     private static Locale[] sampleLocales = {
179         new Locale("ar", "SA"),
180         new Locale("zh", "CN"),
181         new Locale("zh", "TW"),
182         new Locale("iw", "IL"),
183         new Locale("ja", "JP"),
184         new Locale("ko", "KR"),
185         new Locale("it", "IT"),
186         new Locale("th", "TH"),
187         new Locale("ar", "SA"),
188         new Locale("zh", "CN"),
189         new Locale("zh", "CN"),
190         new Locale("zh", "CN"),
191         new Locale("zh", "TW"),
192         new Locale("iw", "IL"),
193         new Locale("ja", "JP"),
194         new Locale("ja", "JP"),
195         new Locale("ko", "KR"),
196         new Locale("it", "IT"),
197         new Locale("it", "IT"),
198         new Locale("th", "TH"),
199     };
200 
201     // expected conversion results for the date strings of the sample locales
202 
203     private static byte[][] expectedBytes = {
204         { 0x31, 0x30, 0x20, (byte) 0xE3, (byte) 0xC7, (byte) 0xED, (byte) 0xE6, 0x2C, 0x20, 0x32, 0x30, 0x30, 0x31, },
205         { 0x32, 0x30, 0x30, 0x31, (byte) 0xC4, (byte) 0xEA, 0x35, (byte) 0xD4, (byte) 0xC2, 0x31, 0x30, (byte) 0xC8, (byte) 0xD5, 0x20, (byte) 0xD0, (byte) 0xC7, (byte) 0xC6, (byte) 0xDA, (byte) 0xCB, (byte) 0xC4},
206         { 0x32, 0x30, 0x30, 0x31, (byte) 0xA6, 0x7E, 0x35, (byte) 0xA4, (byte) 0xEB, 0x31, 0x30, (byte) 0xA4, (byte) 0xE9, 0x20, (byte) 0xAC, (byte)0x50, (byte) 0xB4, (byte) 0xC1, (byte) 0xA5, (byte) 0x7C},
207         { (byte) 0xE9, (byte) 0xE5, (byte) 0xED, 0x20, (byte) 0xE7, (byte) 0xEE, (byte) 0xE9, (byte) 0xF9, (byte) 0xE9, 0x20, 0x31, 0x30, 0x20, (byte) 0xEE, (byte) 0xE0, (byte) 0xE9, 0x20, 0x32, 0x30, 0x30, 0x31, },
208         { 0x32, 0x30, 0x30, 0x31, (byte) 0x94, 0x4E, 0x35, (byte) 0x8C, (byte) 0x8E, 0x31, 0x30, (byte) 0x93, (byte) 0xFA, },
209         { 0x32, 0x30, 0x30, 0x31, (byte) 0xB3, (byte) 0xE2, 0x20, 0x35, (byte) 0xBF, (byte) 0xF9, 0x20, 0x31, 0x30, (byte) 0xC0, (byte) 0xCF, 0x20, (byte) 0xB8, (byte) 0xF1, (byte) 0xBF, (byte) 0xE4, (byte) 0xC0, (byte) 0xCF, },
210         { 0x67, 0x69, 0x6F, 0x76, 0x65, 0x64, (byte) 0xEC, 0x20, 0x31, 0x30, 0x20, 0x6D, 0x61, 0x67, 0x67, 0x69, 0x6F, 0x20, 0x32, 0x30, 0x30, 0x31, },
211         { (byte) 0xC7, (byte) 0xD1, (byte) 0xB9, (byte) 0xBE, (byte) 0xC4, (byte) 0xCB, (byte) 0xD1, (byte) 0xCA, (byte) 0xBA, (byte) 0xB4, (byte) 0xD5, (byte) 0xB7, (byte) 0xD5, (byte) 0xE8, 0x20, 0x31, 0x30, 0x20, (byte) 0xBE, (byte) 0xC4, (byte) 0xC9, (byte) 0xC0, (byte) 0xD2, (byte) 0xA4, (byte) 0xC1, 0x20, (byte) 0xBE, 0x2E, (byte) 0xC8, 0x2E, 0x20, 0x32, 0x35, 0x34, 0x34, },
212         { 0x31, 0x30, 0x20, (byte) 0xE5, (byte) 0xC7, (byte) 0xEA, (byte) 0xE8, 0x2C, 0x20, 0x32, 0x30, 0x30, 0x31, },
213         { 0x32, 0x30, 0x30, 0x31, (byte) 0xC4, (byte) 0xEA, 0x35, (byte) 0xD4, (byte) 0xC2, 0x31, 0x30, (byte) 0xC8, (byte) 0xD5, 0x20, (byte) 0xD0, (byte) 0xC7, (byte) 0xC6, (byte) 0xDA, (byte) 0xCB, (byte) 0xC4},
214         { 0x32, 0x30, 0x30, 0x31, (byte) 0xE5, (byte) 0xB9, (byte) 0xB4, 0x35, (byte) 0xE6, (byte) 0x9C, (byte) 0x88, 0x31, 0x30, (byte) 0xE6, (byte) 0x97, (byte) 0xA5, 0x20, (byte) 0xE6, (byte)0x98, (byte) 0x9F, (byte) 0xE6, (byte) 0x9C, (byte) 0x9F, (byte) 0xE5, (byte) 0x9B, (byte) 0x9B},
215         { 0x32, 0x30, 0x30, 0x31, (byte) 0xC4, (byte) 0xEA, 0x35, (byte) 0xD4, (byte) 0xC2, 0x31, 0x30, (byte) 0xC8, (byte) 0xD5, 0x20, (byte) 0xD0, (byte) 0xC7, (byte) 0xC6, (byte) 0xDA, (byte) 0xCB, (byte) 0xC4},
216         { 0x32, 0x30, 0x30, 0x31, (byte) 0xC8, (byte) 0xA1, 0x35, (byte) 0xC5, (byte) 0xCC, 0x31, 0x30, (byte) 0xC5, (byte) 0xCA, 0x20, (byte) 0xD1, (byte) 0xD3, (byte) 0xDF, (byte) 0xE6, (byte) 0xC6, (byte) 0xBE},
217         { (byte) 0xE9, (byte) 0xE5, (byte) 0xED, 0x20, (byte) 0xE7, (byte) 0xEE, (byte) 0xE9, (byte) 0xF9, (byte) 0xE9, 0x20, 0x31, 0x30, 0x20, (byte) 0xEE, (byte) 0xE0, (byte) 0xE9, 0x20, 0x32, 0x30, 0x30, 0x31, },
218         { 0x32, 0x30, 0x30, 0x31, (byte) 0xC7, (byte) 0xAF, 0x35, (byte) 0xB7, (byte) 0xEE, 0x31, 0x30, (byte) 0xC6, (byte) 0xFC, },
219         { 0x32, 0x30, 0x30, 0x31, (byte) 0x94, 0x4E, 0x35, (byte) 0x8C, (byte) 0x8E, 0x31, 0x30, (byte) 0x93, (byte) 0xFA, },
220         { 0x32, 0x30, 0x30, 0x31, (byte) 0xB3, (byte) 0xE2, 0x20, 0x35, (byte) 0xBF, (byte) 0xF9, 0x20, 0x31, 0x30, (byte) 0xC0, (byte) 0xCF, 0x20, (byte) 0xB8, (byte) 0xF1, (byte) 0xBF, (byte) 0xE4, (byte) 0xC0, (byte) 0xCF, },
221         { 0x67, 0x69, 0x6F, 0x76, 0x65, 0x64, (byte) 0xEC, 0x20, 0x31, 0x30, 0x20, 0x6D, 0x61, 0x67, 0x67, 0x69, 0x6F, 0x20, 0x32, 0x30, 0x30, 0x31, },
222         { 0x67, 0x69, 0x6F, 0x76, 0x65, 0x64, (byte) 0xEC, 0x20, 0x31, 0x30, 0x20, 0x6D, 0x61, 0x67, 0x67, 0x69, 0x6F, 0x20, 0x32, 0x30, 0x30, 0x31, },
223         { (byte) 0xC7, (byte) 0xD1, (byte) 0xB9, (byte) 0xBE, (byte) 0xC4, (byte) 0xCB, (byte) 0xD1, (byte) 0xCA, (byte) 0xBA, (byte) 0xB4, (byte) 0xD5, (byte) 0xB7, (byte) 0xD5, (byte) 0xE8, 0x20, 0x31, 0x30, 0x20, (byte) 0xBE, (byte) 0xC4, (byte) 0xC9, (byte) 0xC0, (byte) 0xD2, (byte) 0xA4, (byte) 0xC1, 0x20, (byte) 0xBE, 0x2E, (byte) 0xC8, 0x2E, 0x20, 0x32, 0x35, 0x34, 0x34, },
224     };
225 
226 
227     private static boolean testRequiredEncodings() {
228         boolean pass = true;
229 
230         for (int i = 0; i < requiredEncodings.length; i++) {
231             String encoding = requiredEncodings[i];
232             Locale sampleLocale = sampleLocales[i];
233             try {
234                 int index = 0;
235                 while (!sampleLocale.equals(requiredLocales[index])) {
236                     index++;
237                 }
238                 byte[] out = requiredLocaleDates[index].getBytes(encoding);
239                 byte[] expected = expectedBytes[i];
240                 if (out.length != expected.length) {
241                     reportConversionError(encoding, expected, out);
242                     pass = false;
243                 } else {
244                     for (int j = 0; j < out.length; j++) {
245                         if (out[j] != expected[j]) {
246                             reportConversionError(encoding, expected, out);
247                             pass = false;
248                             break;
249                         }
250                     }
251                 }
252             } catch (UnsupportedEncodingException e) {
253                 System.out.println("Encoding not available: " + encoding);
254                 pass = false;
255             }
256         }
257         return pass;
258     }
259 
260     private static void reportConversionError(String encoding,
261             byte[] expected, byte[] actual) {
262 
263         System.out.println("Incorrect conversion for encoding: " + encoding);
264         System.out.println("Expected output:");
265         dumpBytes(expected);
266         System.out.println("Actual output:");
267         dumpBytes(actual);
268     }
269 
270     private static void dumpBytes(byte[] bytes) {
271         System.out.print("        { ");
272         for (int i = 0; i < bytes.length; i++) {
273              byte b = bytes[i];
274              if (b < 0) {
275                  System.out.print("(byte) ");
276              }
277              System.out.print("0x" + toHex((b & 0x00F0) >> 4)
278                      + toHex((b & 0x000F)) + ", ");
279         }
280         System.out.println("},");
281     }
282 
283     private static char toHex(int i) {
284         if (i <= 9) {
285             return (char) ('0' + i);
286         } else {
287             return (char) ('A' + i - 10);
288         }
289     }
290 }